// MAIN HEADER FILE FOR CProfiler CLASS
//
// A small profiling class using the Win32 API
//
// v.1.0
// Written by Hernan Di Pietro (May 2003) && Modified by Samuel Batista (September 2008)
// mailto:sambatista@live.com
//
/* 

Author: 
Samuel Batista 2008

E-Mail: 
sambatista@live.com

Date: 
10/08/2008

Description: 
This class was written by Hernan Di Pietro and heavily modified by me.
It logs function calls and the time that each function takes to execute.
If the user desires it also outputs a text LOG file with all functions profiled
and the time each function took to execute. It supports multiple profiled functions
(within loops) and multiple calls to functions that are meant to be profiled once.
You can also profile functions within a functio, so for example, you can profile
the time it takes for something to initialize and profile individual functions
called within that initialize function.

The Console class was written by Gregor S. see the .cpp file for further information.

Usage:
Copy Profiler.h (this file) and Profiler.cpp into the directory
of your application. Insert them into the workspace if you wish.
Next, add the line '#include "Profiler.h"' into one of your source
files and add a pointer to the CProfiler class.
Example Startup:

CProfiler profiler = CProfiler::GetInstance();
profiler->Initialize(parameters);

Then, before a function call call profiler->ProfileStart(params);
and after the function call do profiler->ProfileEnd(params);

Don't forget to call profiler->Shutdown(); after the program has finished
executing, otherwise it won't output the results to a LOG file.

Copyright & disclaimer: 
Do want you want to do with this class: Modify it, extend it to your
needs. Use it in both Freeware, Shareware or commercial applications,
but make sure to leave these comments at the top of this source file 
intact and don't remove my name and E-mail address.
*/
///////////////////////////////////////////////////
// See Profiler.cpp for implementation
//////////////////////////////////////////////////
#pragma once
#include <windows.h>
#include <vector>
using std::vector;
#include <string>
using std::string;

// enumeration for Debug Logging Output Types (or "styles")
enum LOGTYPE { LOG_DEBUG_OUTPUT, LOGCONSOLE, LOGTEXTOUT, LOGALL };		

#pragma region Console Declarations

class CConsole
{
public:
	CConsole() 
	{ 
		hConsole = NULL; 
	};

public:
	// create the console
	bool   Create(const char* szTitle);

	void DisableClose();
	
	// set color for output
	void   Color(WORD wColor = NULL);
	// write output to console
	void   Output(string Output = "");

	// show/hide the console
	void   Show(bool bShow = true);

	// set and get title of console
	void   SetTitle(const char* szTitle);
	char*  GetTitle();

	// get HWND and/or HANDLE of console
	HWND   GetHWND();
	HANDLE GetHandle();

	// clear all output
	void   Clear();

	// close the console and delete it
	void   Close();

private:
	HANDLE hConsole;
};

#pragma endregion

#pragma region Profiler Declarations 

class CProfiler
{
private:

	struct FUNCTION_PROFILE
	{
		string			funcName;
		string			funcLocation;
		string			notes;
		UINT			numTimesCalled;
		UINT			numTotalProfileTimes;
		LARGE_INTEGER	StartCounter;			// start time
		bool   multipleCalls;

		vector<__int64> elapsedTimes;			// Vector of elapsedTimes, necessary for multiple calls to a single profile function.
		__int64 totalElapsedTime;

		FUNCTION_PROFILE()
		{
			funcName = "";
			funcLocation = "";
			notes = "";
			numTimesCalled = 0;
			multipleCalls = false;
			numTotalProfileTimes = 1;
			totalElapsedTime = 0;
			ZeroMemory(&StartCounter,sizeof(StartCounter));
		}
	};

public:
	static CProfiler*	GetInstance(void);
	CConsole*			GetConsole()		{ return &console; }

	void		Initialize(string buildInfo, LOGTYPE logtype = LOG_DEBUG_OUTPUT);
	void		Shutdown();

	void		ProfileStart(string funcName, string funcLocation, string notes = "", bool profileMultipleTimes = false, int numTotalProfileTimesBeforeLog = 1000); // starts profiling
	void 		ProfileEnd  (string funcName, string funcLocation);				 // end profiling		
	void 		LogResults  (int nID);       // Logs the results of the profiling test.
	double		SecsFromTicks ( __int64 ticks);
		
private:
	CProfiler(void);
	~CProfiler(void);	
	CProfiler(const CProfiler &ref);
	CProfiler &operator=(const CProfiler &ref);

	CConsole console;

	string			m_sBuildInfo;
	
	LARGE_INTEGER	m_QPFrequency;		// ticks/sec resolution
	LARGE_INTEGER	m_EndCounter;		// finish time
	DWORD			m_Retval;			// return value for API functions
	LOGTYPE			m_LogType;			// logging type

	bool			m_bLogMultipleNow;

	vector<FUNCTION_PROFILE> m_vProfiledFunctions;	// Vector of all profiled functions, necessary for the LOG file.
};

#pragma endregion
